package com.clei.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.type.TypeFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
 * 用于生产一些偶尔会用到的json字符串
 *
 * @author Y
 */
public final class JsonUtil {

    /**
     * ObjectMapper
     */
    private final static ObjectMapper OM = new ObjectMapper();

    /**
     * ObjectMapper
     */
    private final static ObjectMapper SNAKE_OM = new ObjectMapper();

    // 初始化
    static {
        OM.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, Boolean.FALSE);

        SNAKE_OM.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, Boolean.FALSE);
        SNAKE_OM.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    }

    private JsonUtil() {
    }

    /**
     * 快速生产一个自定义json
     * aa bb
     * cc dd
     * xxx
     * {"aa":"bb","cc":"dd"}
     *
     * @return JSONObject
     */
    public static String getJson() {
        Scanner input = new Scanner(System.in);
        Map<String, String> map = new HashMap<>();
        String str = input.nextLine();
        while (!"xxx".equals(str)) {
            int i = str.indexOf(' ');
            map.put(str.substring(0, i), str.substring(i + 1));
            str = input.nextLine();
        }
        return toJson(map);
    }

    /**
     * toJson
     *
     * @param obj obj
     * @return json
     */
    public static String toJson(Object obj) {
        if (null == obj || obj instanceof String) {
            return String.valueOf(obj);
        }
        String json = null;
        try {
            json = OM.writeValueAsString(obj);
        } catch (Exception e) {
            PrintUtil.log("toJson error obj : {}", obj);
        }
        return json;
    }

    /**
     * parse
     *
     * @param json  json
     * @param clazz class
     * @param <T>   泛型
     * @return T
     */
    public static <T> T parse(String json, Class<T> clazz) {
        T t = null;
        try {
            t = OM.readValue(json, clazz);
        } catch (Exception e) {
            PrintUtil.log("parse error json : {} class : {}", json, clazz.getName());
        }
        return t;
    }

    /**
     * parse
     *
     * @param json    json
     * @param typeRef TypeReference
     * @param <T>     泛型
     * @return T
     */
    public static <T> T parse(String json, TypeReference<T> typeRef) {
        T t = null;
        try {
            t = OM.readValue(json, typeRef);
        } catch (Exception e) {
            PrintUtil.log("parse error json : {} typeRef : {}", json, typeRef.getType().getTypeName());
        }
        return t;
    }

    /**
     * parse
     *
     * @param json    json
     * @param typeRef TypeReference
     * @param <T>     泛型
     * @return T
     */
    public static <T> T parseFromSnake(String json, TypeReference<T> typeRef) {
        T t = null;
        try {
            t = SNAKE_OM.readValue(json, typeRef);
        } catch (Exception e) {
            PrintUtil.log("parse error json : {} typeRef : {}", json, typeRef.getType().getTypeName());
        }
        return t;
    }

    /**
     * parseList
     *
     * @param json  json
     * @param clazz class
     * @param <T>   泛型
     * @return T
     */
    public static <T> List<T> parseList(String json, Class<T> clazz) {
        List<T> list = null;
        try {
            list = OM.readValue(json, TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, clazz));
        } catch (Exception e) {
            PrintUtil.log("parseList error json : {} class : {}", json, clazz.getName());
        }
        return list;
    }
}
